package cn.spring.framework.redis.service;

import cn.spring.framework.redis.config.LzmhRedisProperties;
import cn.spring.framework.redis.core.AbstractCacheOperator;
import cn.spring.framework.redis.core.CacheOperator;
import cn.spring.framework.redis.core.Refresher;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * @author xingkong
 * @Title: RedisCacheOperator
 * @Description: redis缓存操作器
 * @date 2021/11/18 16:06
 */
public class RedisCacheOperator {
    /**
     *  CacheOperator具体实现
     */
    private final InnerRedisCacheOperator innerRedisCacheOperator;

    private RedisCacheOperator(Builder builder) {
        innerRedisCacheOperator = new InnerRedisCacheOperator(builder.lzmhRedisProperties, builder.redisService);
    }

    /**
     * 创建代理
     */
    private CacheOperator createProxy() {
        return (CacheOperator) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {CacheOperator.class}, this.innerRedisCacheOperator);
    }

    public static Builder builder(LzmhRedisProperties lzmhRedisProperties, RedisService redisService) {
        return new Builder(lzmhRedisProperties, redisService);
    }

    /**
     * builder模式
     */
    public static class Builder{
        private LzmhRedisProperties lzmhRedisProperties;
        private RedisService redisService;

        public Builder(LzmhRedisProperties lzmhRedisProperties, RedisService redisService) {
            this.lzmhRedisProperties = lzmhRedisProperties;
            this.redisService = redisService;
        }

        /**
         * 创建对象
         * @return CacheOperator 实现
         */
        public CacheOperator build() {
            RedisCacheOperator redisCacheOperator = new RedisCacheOperator(this);
            return redisCacheOperator.createProxy();
        }
    }

    /**
     * 内部类，实现 InvocationHandler，实现代理，控制访问
     */
    private static class InnerRedisCacheOperator extends AbstractCacheOperator implements CacheOperator, InvocationHandler {

        public InnerRedisCacheOperator(LzmhRedisProperties lzmhRedisProperties, RedisService redisService) {
            super(lzmhRedisProperties, redisService);
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //预处理操作
            this.preProcess();

            String methodName = method.getName();
            Class<?>[] parameterTypes = method.getParameterTypes();

            if (method.getDeclaringClass() == Object.class) {
                return method.invoke(this, args);
            }
            if ("toString".equals(methodName) && parameterTypes.length == 0) {
                return this.toString();
            }
            if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
                return this.hashCode();
            }
            if ("equals".equals(methodName) && parameterTypes.length == 1) {
                return this.equals(args[0]);
            }
            String key = (String) args[0];
            //过滤器链前置处理

            Object result = this.failbackCacheOperator.invoke(method, args);

            //过滤器链后置处理


            return result;
        }

        @Override
        public String get(String key, long expire, Refresher<String> flusher) {
            return stringOperator.get(key, expire, flusher);
        }

        @Override
        public Future<String> getAsync(String key, long expire, Refresher<String> flusher) {
            return stringOperator.getAsync(key, expire, flusher);
        }

        @Override
        public Future<String> getAsync(String key, long expire, Refresher<String> flusher,
                                       ExecutorService executorService) {
            return stringOperator.getAsync(key, expire, flusher, executorService);
        }

        @Override
        public void del(String key) {
            this.stringOperator.del(key);
        }

        @Override
        public List<String> lRange(String key, long start, long end, long expire, Refresher<List<String>> refresher) {
            return listOperator.lRange(key, start, end, expire, refresher);
        }

        @Override
        public String lPop(String key, long expire, Refresher<List<String>> refresher) {
            return listOperator.lPop(key, expire, refresher);
        }

        @Override
        public String rPop(String key, long expire, Refresher<List<String>> flusher) {
            return listOperator.rPop(key, expire, flusher);
        }

        @Override
        public Future<List<String>> lRangeAsync(String key, long start, long end, long expire,
                                                Refresher<List<String>> flusher) {
            return listOperator.lRangeAsync(key, start, end, expire, flusher);
        }

        @Override
        public Future<List<String>> lRangeAsync(String key, long start, long end, long expire,
                                                Refresher<List<String>> flusher, ExecutorService executorService) {
            return listOperator.lRangeAsync(key, start, end, expire, flusher, executorService);
        }

        @Override
        public Future<List<String>> lPopAsync(String key, long expire, Refresher<List<String>> flusher) {
            return listOperator.lPopAsync(key, expire, flusher);
        }

        @Override
        public Future<List<String>> lPopAsync(String key, long expire, Refresher<List<String>> flusher,
                                              ExecutorService executorService) {
            return listOperator.lPopAsync(key, expire, flusher, executorService);
        }

        @Override
        public Future<List<String>> rPopAsync(String key, long expire, Refresher<List<String>> flusher) {
            return listOperator.rPopAsync(key, expire, flusher);
        }

        @Override
        public Future<List<String>> rPopAsync(String key, long expire, Refresher<List<String>> flusher,
                                              ExecutorService executorService) {
            return listOperator.rPopAsync(key, expire, flusher, executorService);
        }

        @Override
        public Map<String, Object> hGetAll(String key, long expire, Refresher<Map<String, Object>> refresher) {
            return mapOperator.hGetAll(key, expire, refresher);
        }

        @Override
        public Future<Map<String, Object>> hGetAllAsync(String key, long expire, Refresher<Map<String, Object>> refresher) {
            return mapOperator.hGetAllAsync(key, expire, refresher);
        }

        @Override
        public Future<Map<String, Object>> hGetAllAsync(String key, long expire, Refresher<Map<String, Object>> refresher
                , ExecutorService executorService) {
            return mapOperator.hGetAllAsync(key, expire, refresher, executorService);
        }

        @Override
        public Object hGet(String key, String field, long expire, Refresher<Map<String, Object>> refresher) {
            return mapOperator.hGet(key, field, expire, refresher);
        }

        @Override
        public Future<Map<String, Object>> hGetAsync(String key, String field, long expire,
                                                     Refresher<Map<String, Object>> fluster) {
            return mapOperator.hGetAsync(key, field, expire, fluster);
        }

        @Override
        public Future<Map<String, Object>> hGetAsync(String key, String field, long expire,
                                                     Refresher<Map<String, Object>> fluster,
                                                     ExecutorService executorService) {
            return mapOperator.hGetAsync(key, field, expire, fluster, executorService);
        }

        @Override
        public Set<String> sMembers(String key, long expire, Refresher<Set<String>> flusher) {
            return setOperator.sMembers(key, expire, flusher);
        }

        @Override
        public Future<Set<String>> sMembersAsync(String key, long expire, Refresher<Set<String>> flusher) {
            return setOperator.sMembersAsync(key, expire, flusher);
        }

        @Override
        public Future<Set<String>> sMembersAsync(String key, long expire, Refresher<Set<String>> flusher,
                                                 ExecutorService executorService) {
            return setOperator.sMembersAsync(key, expire, flusher, executorService);
        }
    }
}
